package com.song.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.song.entity.Lend;
import com.song.entity.LendItem;
import com.song.entity.UserAccount;
import com.song.entity.bo.TransFlowBO;
import com.song.entity.vo.InvestVO;
import com.song.enums.LendStatusEnum;
import com.song.enums.TransTypeEnum;
import com.song.exception.BusinessException;
import com.song.hfb.FormHelper;
import com.song.hfb.HfbConst;
import com.song.hfb.RequestHelper;
import com.song.mapper.LendItemMapper;
import com.song.mapper.LendMapper;
import com.song.mapper.UserAccountMapper;
import com.song.service.LendItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.song.service.LendService;
import com.song.service.TransFlowService;
import com.song.service.UserBindService;
import com.song.util.LendNoUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author Song
 * @since 2025-01-03
 */
@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    @Autowired
    private LendMapper lendMapper;

    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private LendService lendService;

    @Autowired
    private UserBindService userBindService;

    @Autowired
    private TransFlowService transFlowService;

    /**
     * 用户提交投标数据的方法
     * @param investVO
     * @return
     */
    @Override
    public String commitInvest(InvestVO investVO) {
        Long lendId = investVO.getLendId();//从前端获取标的id
        //要想进行投标，当前标的需要满足3个条件---
        // 1.标的状态是募资中 2.账户余额充足 3.标的不能超卖（标的中已经有的钱加上本次用户投资的钱不能超过标的的额定金额）
        Lend lend = lendMapper.selectById(lendId);//获取标的对象
        if (lend.getStatus() != LendStatusEnum.INVEST_RUN.getStatus()){
            //不是募资中
            return "fail";
        }

        //UserAccount userAccount = userAccountMapper.selectById(lend.getUserId());
        //if (userAccount.getAmount().compareTo(NumberUtils.createBigDecimal(investVO.getInvestAmount())) < 0){
        //    //账户不充足
        //    return "fail";
        //}

        if (lend.getInvestAmount().add(NumberUtils.createBigDecimal(investVO.getInvestAmount())).compareTo(lend.getAmount()) > 0){
            //超卖
            return "fail";
        }
        //到这里说明都正常---生成投资条目
        LendItem lendItem = new LendItem();//获取条目对象

        String lendItemNo = LendNoUtils.getLendItemNo();//生成投资条目编号
        lendItem.setLendItemNo(lendItemNo);

        lendItem.setLendId(investVO.getLendId());//标的编号
        lendItem.setInvestAmount(new BigDecimal(investVO.getInvestAmount()));//投资金额
        lendItem.setLendYearRate(lend.getLendYearRate());//年化率
        lendItem.setLendStartDate(lend.getLendStartDate());//开始时间
        lendItem.setInvestTime(new Date());//投资时间
        lendItem.setLendEndDate(lend.getLendEndDate());//投资结束时间
        //计算预期收益
        BigDecimal interestCount = lendService.getInterestCount(lendItem.getInvestAmount(), lendItem.getLendYearRate(), lend.getPeriod(), lend.getReturnMethod());
        lendItem.setExpectAmount(interestCount);//预期收益
        lendItem.setRealAmount(new BigDecimal(0));//实际收益
        lendItem.setStatus(0);//投资条目状态（0：默认 1：已支付 2：已还款）

        //插入投资条目
        baseMapper.insert(lendItem);


        //投资成功要去汇付宝


        String bindCode=  userBindService.getBindCodeByUserId(investVO.getInvestUserId());//
        String benefitBindCode=  userBindService.getBindCodeByUserId(lend.getUserId());

        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);//给商户分配的唯一标识
        paramMap.put("voteBindCode",bindCode);//投资人绑定协议号
        paramMap.put("benefitBindCode",benefitBindCode);//借款人绑定协议号
        paramMap.put("agentProjectCode",lend.getLendNo());//项目编号
        paramMap.put("agentProjectName",lend.getTitle());//项目名称
        paramMap.put("agentBillNo",lendItemNo);//商户订单号
        paramMap.put("voteAmt",investVO.getInvestAmount());// 投资金额
        paramMap.put("voteFeeAmt",new BigDecimal(0));// 商户手续费
        paramMap.put("projectAmt",new BigDecimal(investVO.getInvestAmount()));// 总金额  这就是10w
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);//绑定完成后同步返回商户的完整地址
        paramMap.put("notifyUrl",HfbConst.INVEST_NOTIFY_URL);//绑定完成后异步通知商户的完整地址。
        paramMap.put("timestamp",new Date().getTime());//时间戳
        paramMap.put("sign", RequestHelper.getSign(paramMap));//验签参数

        String form = FormHelper.buildForm(HfbConst.INVEST_URL, paramMap);//第一个参数是 用户绑定的url   ，第二个 接口需要的参数 !!


        return form;
    }

    /**
     * 投标成功之后的操作---产生流水记录
     * @param objectMap
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notifyss(Map<String, Object> objectMap) {

        //获取投资编号
        String agentBillNo = (String) objectMap.get("agentBillNo");
        //幂等性 !!!判断表中是否已经存在
        boolean result = transFlowService.isSaveTransFlow(agentBillNo);
        if(result){
            //存在，不做操作直接返回
            System.out.println("幂等性返回!!");
            return;
        }

        //到这里说明不存在
        /**
         * 1.获取投资人绑定的协议号
         * 2.获取投资金额
         * 3.投资之后要修改账户的余额和冻结金额
         * 4.修改用户投资状态为已经支付
         * 5.支出了 ，产生流水记录
         */

        //获取 vote_bind_code	string	50	是	投资人绑定协议号
        String voteBindCode = (String) objectMap.get("voteBindCode");
        //vote_amt	decimal		是	投资金额
        //(含商户奖励给投资人的金额，即包括vote_prize_amt)
        String voteAmt = (String) objectMap.get("voteAmt");
        //修改余额和冻结的金额
        userAccountMapper.updateUserAccount(voteBindCode, new BigDecimal("-"+voteAmt), new BigDecimal(voteAmt));

        //修改投资记录的状态变为 已经支付
        LendItem lendItem = this.getByLendItemNo(agentBillNo);
        lendItem.setStatus(1);
        baseMapper.updateById(lendItem);

        //修改标的信息  投资人数 已经投资的金额
        Long lendId = lendItem.getLendId();
        Lend lend = lendMapper.selectById(lendId);
        lend.setInvestNum(lend.getInvestNum()+1);
        lend.setInvestAmount(lend.getInvestAmount().add(lendItem.getInvestAmount()));
        lendMapper.updateById(lend);

            //动钱了 交易流水
        /*
        private String agentBillNo;//商户充值订单号
        private BigDecimal amount;//账户的可用余额
        private String bindCode;//绑定
        private TransTypeEnum transTypeEnum;//绑定协议号
        private String memo;//备忘
         */
        TransFlowBO transFlowBO = new TransFlowBO(agentBillNo, new BigDecimal(voteAmt), voteBindCode, TransTypeEnum.INVEST_LOCK, "项目编号:"+lend.getLendNo()+",项目名称："+lend.getTitle());

    }

    @Override
    public LendItem getByLendItemNo(String lendItemNo) {
        QueryWrapper<LendItem> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_item_no",lendItemNo);
        return  baseMapper.selectOne(wrapper);
    }

    @Override
    public List<LendItem> selectLendById(Long lendId, int status) {
        QueryWrapper<LendItem> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_id",lendId);
        wrapper.eq("status",status);
        List<LendItem> lendItemList = baseMapper.selectList(wrapper);

        return lendItemList;
    }
}
